package com.smi.cn.satemachine;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.alibaba.fastjson.JSON;

import org.springframework.transaction.TransactionStatus;

/**
 * Created by zhangyanfei on 2017/7/26.
 *
 * @author zhangyanfei
 * @date 2017/07/26
 */
public class StateMachineContext extends BaseEntity{
    private Map<MessageKeyEnum,Object> messages=new HashMap<>();
    private TransactionStatus transactionStatus;

    public <T> T get(MessageKeyEnum key){
        if(messages==null||key==null){
            return null;
        }
        Object value=messages.get(key);
        if (value==null){
            return null;
        }
        //做下验证 是否key这个参数有效
        if (!key.getMsgClass().isAssignableFrom(value.getClass())){
            throw new IllegalArgumentException("Incorrect type specified for header "
                + "'"+key+"'.Expected ["+key.getMsgClass()+"] but actual type is ["+value .getClass()+"]");
        }
        return (T)value;
    }

    /**
     *
     * @param key
     * @param initialFunc 回调接口
     * @param <T>
     * @return
     */
    public <T> T getIfPresent(MessageKeyEnum key,Func<T> initialFunc){
        T result=get(key);

        if (result!=null&&initialFunc!=null){
            result=initialFunc.invoke();
            messages.put(key,result);
        }

        return result;
    }

    public int size() {
        return messages.size();
    }

    public boolean isEmpty() {
        return messages.isEmpty();
    }

    public boolean containsKey(MessageKeyEnum key) {
        return messages.containsKey(key);
    }

    public boolean containsValue(Object value) {
        return messages.containsValue(value);
    }

    public <T> T put(MessageKeyEnum key, Object value) {
        if (messages == null || key == null) {
            return null;
        }
        if (value == null) {
            return null;
        }
        if (!key.getMsgClass().isAssignableFrom(value.getClass())) {
            throw new IllegalArgumentException("Incorrect type specified for header '" +
                key + "'. Expected [" + key.getMsgClass() + "] but actual type is [" + value.getClass() + "]");
        }
        return (T)messages.put(key, value);
    }

    public <T> T remove(MessageKeyEnum key) {
        if (messages == null || key == null) {
            return null;
        }
        return (T)messages.remove(key);
    }

    public void putAll(Map<? extends MessageKeyEnum, ?> m) {
        messages.putAll(m);
    }

    public void clear() {
        messages.clear();
    }

    public Set<MessageKeyEnum> keySet() {
        return messages.keySet();
    }

    public Collection<Object> values() {
        return messages.values();
    }

    public Set<Entry<MessageKeyEnum, Object>> entrySet() {
        return messages.entrySet();
    }

    public TransactionStatus getTransactionStatus() {
        return transactionStatus;
    }

    public void setTransactionStatus(TransactionStatus transactionStatus) {
        this.transactionStatus = transactionStatus;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this.messages);
    }
}
